using System;
using System.Collections.Generic;
using System.Text;

namespace WOWEquipOptimizer.Rogue
{
    class Combat : MeleeDD
    {
        public Combat()
            : base()
        {
            AllowTwoHand = false;
            AllowDualWield = true; 
            m_Base = new List<Attribute>();
            m_Base.Add(new Attribute(AttributeName.Health, 3500));
            m_Base.Add(new Attribute(AttributeName.Stamina, 94));
            m_Base.Add(new Attribute(AttributeName.Strength, 98));
            m_Base.Add(new Attribute(AttributeName.AttackPower, 120));
            m_Base.Add(new Attribute(AttributeName.CritRating, 5.11f*CritRating));
            m_Base.Add(new Attribute(AttributeName.Agility, 158));
            m_Base.Add(new Attribute(AttributeName.CritRating, 5 * CritRating));
            m_Base.Add(new Attribute(AttributeName.HitRating, 5 * HitRating));           
            foreach (Attribute attr in m_Base)
            {
                handleAttribute(attr);
            }
            Buff soe = new Buff("Strength of Earth", new List<Attribute>());
            soe.Attributes.Add(new Attribute(AttributeName.Strength, 88 * 1.15f));
            Buffs.Add(soe);
            Buff wf = new Buff("Windfury Totem", new List<Attribute>());
            wf.Attributes.Add(new Attribute(AttributeName.Special, 12345678));
            Buffs.Add(wf);
            m_BaseWeaponSkills.Add(new WeaponSkill(WeaponType.Dagger, 10 * WeaponSkillRating));
            m_BaseWeaponSkills.Add(new WeaponSkill(WeaponType.Sword, 10 * WeaponSkillRating));
            m_BaseWeaponSkills.Add(new WeaponSkill(WeaponType.FistWeapon, 10 * WeaponSkillRating));

        }
        // WDPS1, WDPS2, WS1, WS2, Crit,Hit, AP, Haste,health
        public override void handleAttribute(Attribute attr)
        {
            switch (attr.Type)
            {
                case AttributeName.Agility:
                    m_Equip[AttributeName.CritRating] += (attr.Value * (HasBlessingOfKings ? 1.1f : 1.0f) / 40) * CritRating;
                    m_Equip[AttributeName.AttackPower] += attr.Value * (HasBlessingOfKings ? 1.1f : 1.0f);
                    break;
                case AttributeName.CritMeleeRating:
                case AttributeName.CritRating:
                    m_Equip[AttributeName.CritRating] += attr.Value;
                    break;
                case AttributeName.HitMeleeRating:
                case AttributeName.HitRating:
                    m_Equip[AttributeName.HitRating] += attr.Value;
                    break;
                case AttributeName.HasteDirect:
                    m_Equip[attr.Type] = (((1 + (m_Equip[attr.Type] / HasteRating) / 100f) * (1 + attr.Value / 100)) - 1) * HasteRating * 100;
                    break;
                default:
                    base.handleAttribute(attr);
                    break;
            }
        }
        public override float evaluateTF()
        {
            float wdps1 = (float)m_Equip[AttributeName.MHWDPS];
            float wdps2 = (float)m_Equip[AttributeName.OHWDPS];
            float ws1 = (float)m_Equip[AttributeName.MHWS];
            float ws2 = (float)m_Equip[AttributeName.OHWS];
            float crit = (float)m_Equip[AttributeName.CritRating] / CritRating;
            float hit = (float)m_Equip[AttributeName.HitRating] / HitRating;
            float baseap = (float)m_Equip[AttributeName.AttackPower];
            float haste = (float)m_Equip[AttributeName.HasteRating] / HasteRating;
            if (wdps1 > 0 && ws1 > 0 && wdps2 > 0 && ws2 > 0)
            {
                bool swordspecmh = false;
                bool swordspecoh = false;
                bool daggermh = false;
                bool daggeroh = false;
                bool fistmh = false;
                bool fistoh = false;
                bool macemh = false;
                bool maceoh = false;
                Weapon mhweapon = (Weapon)m_Items[(int)SlotName.MainHand];
                Weapon ohweapon = (Weapon)m_Items[(int)SlotName.OffHand];
                if (mhweapon.Type == WeaponType.Sword)
                {
                    swordspecmh = true;
                    if (ohweapon.Type == WeaponType.Sword)
                    {
                        swordspecoh = true;
                    }
                }
                else if (mhweapon.Type == WeaponType.Mace)
                {
                    macemh = true;
                    m_WeaponSkills.Add(new WeaponSkill(WeaponType.Mace, 10 * WeaponSkillRating));
                    if (ohweapon.Type == WeaponType.Mace)
                    {
                        maceoh = true;
                    }

                }
                else if (mhweapon.Type == WeaponType.Dagger)
                {
                    daggermh = true;
                    if (ohweapon.Type == WeaponType.Dagger)
                    {
                        daggeroh = true;
                    }
                }
                else if (mhweapon.Type == WeaponType.FistWeapon)
                {
                    fistmh = true;
                    if (ohweapon.Type == WeaponType.FistWeapon)
                    {
                        fistoh = true;
                    }
                }
                float[] weaponskills = evaluteWeaponSkills();
                // end calculating special weapon talents
                // sinister strike when possible, slice&dice up all the time, eviscerate otherwise, slightly simplified
                // simplified sequence = snd,rupture,snd,rupture ...
                // every 30s basically one rupture
                float glancingreduction = 25; // XX% reduced damage
                float glancingchance = 25; // chance to happen == XX%
                float glancing = glancingreduction * glancingchance / 100; // this value is used in the closed-form of the attacktable below
                float dodge = 5.6f; // 5.6% dodge chance of the boss
                float ssenergy = 40;
                float hitwhite = (float)Math.Min(100 - 5 - 19 - 3.0f - 0.6f + hit, 100); // 100% - 5% base - 19% dw - 3% bossmalus- 0.6% wskilldifference + hit, upto array maximum of 100
                float hityellow = (float)Math.Min(100 - 5 - 3.0f - 0.6f + hit, 100);// 100% - 5% base - 3% bossmalus - 0.6% wskilldifference + hit, upto array maximum of 100
                float ap = baseap;
                float calchaste = 1.3f * (1 + haste / 100) * (1 + (20f / (120f / 15f)) / 100f); // +snd + haste + blade flurry
                float avgspeed = (ws1 / calchaste + ws2 / calchaste) / 2;
                float critmh = crit + ((daggermh | fistmh) ? 5f : 0f) + weaponskills[0] * 0.2f;
                float critoh = crit + ((daggeroh | fistoh) ? 5f : 0f) + weaponskills[1] * 0.2f;
                float critavg = (critmh + critoh) / 2;
                float eps = 10 + 2 + 25f / (40f / (10f + 2f) * 5f) + ((15f * 0.2f) / (ws2 / calchaste)) * hitwhite / 100f;// 13.5 energy per second should be correct, without combat potency, 2 from adrenaline rush (avg), 1.5 from Relentless strikes, combat potency should be max 3
                // energy per second done
                float sndtime = 21 * 1.45f; // 5p snd (30.45s) for 5p snd,
                // sndtime is not used
                float hitwhitemh = (float)Math.Min(hitwhite + weaponskills[0] * 0.2f, 100);
                float hitwhiteoh = (float)Math.Min(hitwhite + weaponskills[1] * 0.2f, 100);
                float hityellowmh = (float)Math.Min(hityellow + weaponskills[0] * 0.2f, 100);
                float hityellowoh = (float)Math.Min(hityellow + weaponskills[1] * 0.2f, 100);
                float dodgemh = (float)Math.Max(dodge - weaponskills[0] * 0.1f, 0);
                float dodgeoh = (float)Math.Max(dodge - weaponskills[1] * 0.1f, 0);
                float ssps = eps / ssenergy; // ~0.4 combopoints per second = 12s for 5p == sinister strikes per second
                float instantps = ssps + 1 / 30f + 1 / 30f; // sinister strikes per second + rupture every 30s and snd every ~30
                float instantmult = daggermh ? 1.7f : 2.4f; // instant mult for ss
                float instantdmg = wdps1 * ws1;
                if (this.SpecialValues.Contains("22071316"))
                {
                    ap += Math.Min(10.0f / avgspeed * (critavg / 100f) * 0.1f * 340f, 340f);
                }
                float ssdps = 1 / 100f * (hityellowmh + 1.3f * critmh) * ssps * 1.06f * (instantdmg + ap / 14f * instantmult + 98);
                float mhwhitedps = 1 / 100f * (hitwhitemh + critmh - glancing - dodgemh) * (wdps1 + ap / 14f); // normal   mh white swing dps
                float ohwhitedps = 0.75f * 1 / 100f * (hitwhitemh + critmh - glancing - dodgeoh) * (wdps2 + ap / 14f); // normal ohindex swing dps
                float swordspecmult = 1 + ((swordspecmh ? (instantps + (1 / (ws1 / calchaste))) : 0f) + (swordspecoh ? (1 / (ws2 / calchaste)) : 0f)) * 0.05f; // swordspec
                float ipoisondps = 1 / 100f * (hitwhiteoh - dodgeoh) * ((170 * 0.2f)/(ws2 / calchaste)); // instant poison dps
                float rdps = 1 / 100f * hityellowmh * (1000 + 0.24f * ap) / 30f; // rupture dmg per second
                float evidps = 1 / 100f * (hityellowmh + critmh) * 1.15f * 1.06f * (985 + 0.15f * ap) / 30f;
                float wfdps = 0;
                if (this.SpecialValues.Contains("12345678"))
                {
                    float wfap = ap + 445 * 1.3f;
                    wfdps = 1 / 100f * 1 / 100f * (hitwhitemh - dodgemh) * (hityellowmh + critmh - dodgemh) * 0.2f * (wdps1 + wfap / 14); // wf stuff
                }
                float finaldps = calchaste * (swordspecmult * Character.Armor * (mhwhitedps + ohwhitedps)) + 1.1f * (Character.Armor * (ssdps + wfdps) + rdps + ipoisondps); // sum it up put haste as array mult 
                CleanUp();
                return CondFactor * finaldps;
            }
            else return -1;
        }
        // 
        public override List<Item> filterEquip(List<Item> input)
        {
            input = base.filterEquip(input);
            List<Item> retval = new List<Item>();
            foreach (Item item in input)
            {
                if ((item.AllowableClasses & CharacterClass.Rogue) == 0) continue;
                if(item.GetType() == typeof(Weapon))
                {
                    Weapon weapon = (Weapon)item;
                    if (weapon.Type == WeaponType.Axe) continue;
                    if (weapon.TwoHand) continue;
                }
                else if(item.GetType() == typeof(Armor))
                {
                    Armor armor = (Armor)item;
                    if ((armor.Type & ArmorProficiency.Leather) == 0) continue;
                    if (armor.Slot == ArmorSlot.OffHand) continue;
                }
                if (SetBlacklist.Contains(item.Set.Name)) continue;
                if (ItemBlacklist.Contains(item.Name)) continue;
                retval.Add(item);
            }
            return handleWhiteList(retval);
        }
        public override bool evaluateBuild(int[] build)
        {
            if (build[1] >= 41 && build[0] >= 13)
            {
                return true;
            }
            else return false;
        }
    }
}

